import Module from './Module';
import $ from 'jquery';

class Uploader extends Module {
  _init() {
    this.files = [];
    this.queue = [];
    this.id = ++Uploader.count;
    this.on('uploadcomplete', (e, file) => {
      this.files.splice($.inArray(file, this.files), 1);
      if (this.queue.length > 0 && this.files.length < this.opts.connectionCount) {
        return this.upload(this.queue.shift());
      } else {
        return this.uploading = false;
      }
    });
    return $(window).on(`beforeunload.uploader-${this.id}`,  e => {
      if (!this.uploading) {
        return;
      }
      e.originalEvent.returnValue = this._t('leaveConfirm');
      return this._t('leaveConfirm');
    });
  }

  upload(file, opts) {
    let key;
    opts = opts || {};
    if (file == null) return;
    
    if (_.isArray(file) || file instanceof FileList) {
      file.forEach((f)=>this.upload(f, opts));
    } else if ($(file).is('input:file')) {
      key = $(file).attr('name');
      if (key) {
        opts.fileKey = key;
      }
      this.upload($.makeArray($(file)[0].files), opts);
    } else if (!file.id || !file.obj) {
      file = this.getFile(file);
    }
    if (!(file && file.obj)) {
      return;
    }
    $.extend(file, opts);
    if (this.files.length >= this.opts.connectionCount) {
      this.queue.push(file);
      return;
    }
    if (this.triggerHandler('beforeupload', [file]) === false) {
      return;
    }
    this.files.push(file);
    this._xhrUpload(file);
    return this.uploading = true;
  }

  getFile(fileObj) {
    let name;
    let ref;
    let ref1;
    if (fileObj instanceof window.File || fileObj instanceof window.Blob) {
      name = (ref = fileObj.fileName) != null ? ref : fileObj.name;
    } else {
      return null;
    }
    return {
      id: this.generateId(),
      url: this.opts.url,
      params: this.opts.params,
      fileKey: this.opts.fileKey,
      name,
      size: (ref1 = fileObj.fileSize) != null ? ref1 : fileObj.size,
      ext: name ? name.split('.').pop().toLowerCase() : '',
      obj: fileObj
    };
  }

  _xhrUpload(file) {
    let formData;
    let k;
    let ref;
    let v;
    formData = new FormData();
    formData.append(file.fileKey, file.obj);
    formData.append("original_filename", file.name);
    if (file.params) {
      ref = file.params;
      for (k in ref) {
        v = ref[k];
        formData.append(k, v);
      }
    }
    return file.xhr = $.ajax({
      url: file.url,
      data: formData,
      processData: false,
      contentType: false,
      type: 'POST',
      headers: {
        'X-File-Name': encodeURIComponent(file.name)
      },
      xhr() {
        let req;
        req = $.ajaxSettings.xhr();
        if (req) {
          req.upload.onprogress = ((_this => e => _this.progress(e)))(this);
        }
        return req;
      },
      progress: ((_this => e => {
        if (!e.lengthComputable) {
          return;
        }
        return _this.trigger('uploadprogress', [file, e.loaded, e.total]);
      }))(this),
      error: ((_this => (xhr, status) => _this.trigger('uploaderror', [file, xhr, status])))(this),
      success: ((_this => result => {
        _this.trigger('uploadprogress', [file, file.size, file.size]);
        _this.trigger('uploadsuccess', [file, result]);
        return $(document).trigger('uploadsuccess', [file, result, _this]);
      }))(this),
      complete: ((_this => (xhr) => _this.trigger('uploadcomplete', [file, xhr.responseText])))(this)
    });
  }

  cancel(file) {
    let f;
    let i;
    let len;
    let ref;
    if (!file.id) {
      ref = this.files;
      for (i = 0, len = ref.length; i < len; i++) {
        f = ref[i];
        if (f.id === file * 1) {
          file = f;
          break;
        }
      }
    }
    this.trigger('uploadcancel', [file]);
    if (file.xhr) {
      file.xhr.abort();
    }
    return file.xhr = null;
  }

  readImageFile(fileObj, callback) {
    let fileReader;
    let img;
    if (!$.isFunction(callback)) {
      return;
    }
    img = new Image();
    img.onload = () => callback(img);
    img.onerror = () => callback();
    if (window.FileReader && FileReader.prototype.readAsDataURL && /^image/.test(fileObj.type)) {
      fileReader = new FileReader();
      fileReader.onload = e => img.src = e.target.result;
      return fileReader.readAsDataURL(fileObj);
    } else {
      return callback();
    }
  }

  destroy() {
    let file;
    let i;
    let len;
    let ref;
    this.queue.length = 0;
    ref = this.files;
    for (i = 0, len = ref.length; i < len; i++) {
      file = ref[i];
      this.cancel(file);
    }
    $(window).off(`.uploader-${this.id}`);
    return $(document).off(`.uploader-${this.id}`);
  }
}

Uploader.count = 0;

Uploader.prototype.opts = {
  url: '',
  params: null,
  fileKey: 'url',
  connectionCount: 3
};

Uploader.prototype.generateId = ((() => {
  let id;
  id = 0;
  return () => id += 1;
}))();

Uploader.i18n = {
  'zh-CN': {
    leaveConfirm: '正在上传文件，如果离开上传会自动取消'
  }
};

Uploader.locale = 'zh-CN';

export default opts => new Uploader(opts);

